/**
 *                            License
 * THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS  
 * CREATIVE COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). 
 * THE WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE LAW.  
 * ANY USE OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE OR  
 * COPYRIGHT LAW IS PROHIBITED.
 * 
 * BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND  
 * AGREE TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE  
 * MAY BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS CONTAINED 
 * HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND CONDITIONS.
 * 
 */
package com.lineage.server.packetserver;

import java.util.Calendar;
import java.util.Iterator;
import java.util.TimeZone;

import com.lineage.configure.Config;
import com.lineage.server.Account;
import com.lineage.server.codes.Opcodes;
import com.lineage.server.model.L1World;
import com.lineage.server.model.Instance.L1PcInstance;

/**
 * 封包盒子:部分技能图标(右上角Icon)以及特效、对话窗口、系统提示信息等等.
 */
public final class S_PacketBox extends ServerBasePacket {
    /** 返回服务器数据包类型的文字信息. */
    private static final String S_PACKETBOX = "[S] S_PacketBox";
    /** . */
    private byte[] _byte = null;

    // *** S_107 sub code list ***
    // 1:Kent 2:Orc 3:WW 4:Giran 5:Heine 6:Dwarf 7:Aden 8:Diad 9:城名9 ...
    /** C(id) H(?): %s的攻城战开始。. */
    public static final int MSG_WAR_BEGIN = 0;
    /** C(id) H(?): %s的攻城战结束。. */
    public static final int MSG_WAR_END = 1;
    /** C(id) H(?): %s的攻城战正在进行中。. */
    public static final int MSG_WAR_GOING = 2;
    /** -: 已经掌握了城堡的主导权。 (音乐变化). */
    public static final int MSG_WAR_INITIATIVE = 3;
    /** -: 已占领城堡。. */
    public static final int MSG_WAR_OCCUPY = 4;
    /** ?: 结束决斗。 (音乐变化). */
    public static final int MSG_DUEL = 5;
    /** 提示信息：您没有发送出任何简讯。/ 您共发出 %d 通天堂简讯。C(count). */
    public static final int MSG_SMS_SENT = 6;
    /** 提示信息:俩人的结婚在所有人的祝福下完成。 (音乐变化). */
    public static final int MSG_MARRIED = 9;
    /** C(weight): 重量(30段阶). */
    public static final int WEIGHT = 10;
    /** C(food): 饱食度(30段阶). */
    public static final int FOOD = 11;
    /** C(0) C(level): 等级%d以下才能使用此道具。 (0~49以外不显示). */
    public static final int MSG_LEVEL_OVER = 12;
    /** UB情报HTML. */
    public static final int HTML_UB = 14;
    /**
     * C(id).<br>
     * 1:感觉到在身上有的精灵力量被空气中融化。<br>
     * 2:忽然全身充满了%s的灵力。火。<br>
     * 3:忽然全身充满了%s的灵力。水。<br>
     * 4:忽然全身充满了%s的灵力。风。<br>
     * 5:忽然全身充满了%s的灵力。地。<br>
     */
    public static final int MSG_ELF = 15;
    /** C(count) S(name)...: 开启拒绝名单. */
    public static final int ADD_EXCLUDE2 = 17;
    /** S(name): 增加到拒绝名单. */
    public static final int ADD_EXCLUDE = 18;
    /** S(name): 移除出拒绝名单. */
    public static final int REM_EXCLUDE = 19;
    /** 状态图示:技能图标1. */
    public static final int ICONS1 = 20;
    /** 状态图示:技能图标2. */
    public static final int ICONS2 = 21;
    /** 状态图示:光系技能. */
    public static final int ICON_AURA = 22;
    /** 提示信息:新村长由%s选出 S(name). */
    public static final int MSG_TOWN_LEADER = 23;
    /**
     * C(id): 你的阶级变更为%s。.<br>
     * id - 1:见习 2:一般 3:守护骑士
     */
    public static final int MSG_RANK_CHANGED = 27;
    /** 提示信息:%s 血盟的 %s打败了反王 %s 血盟成为新主人 D(?) S(name) S(clanname). */
    public static final int MSG_WIN_LASTAVARD = 30;
    /** 提示信息:\f1你觉得舒服多了。. */
    public static final int MSG_FEEL_GOOD = 31;
    /** 不明。C_30客户端会传回一个封包. */
    public static final int SOMETHING1 = 33;
    /** 状态图示:蓝水 H(time):. */
    public static final int ICON_BLUEPOTION = 34;
    /** 状态图示:变身 H(time):. */
    public static final int ICON_POLYMORPH = 35;
    /** 状态图示:禁言 H(time):. */
    public static final int ICON_CHATBAN = 36;

    /** 不明。C_7パケットが飞ぶ。C_7はペットのメニューを开いたときにも飞ぶ。 */
    public static final int SOMETHING2 = 37;

    /** 血盟成员清单HTML. */
    public static final int HTML_CLAN1 = 38;
    /** 状态图示:圣结界 H(time):. */
    public static final int ICON_I2H = 40;
    /** 更新角色使用的快捷键. */
    public static final int CHARACTER_CONFIG = 41;
    /** 角色选择视窗. */
    public static final int LOGOUT = 42;
    /** 提示信息:战斗中无法重新开始。. */
    public static final int MSG_CANT_LOGOUT = 43;
    /** 状态图示:风之枷锁. */
    public static final int ICON_WIND_SHACKLE = 44;
    /**
     * GM WHO显示的在线玩家HTML 点选可直接传送至身边.<br>
     * C(count) D(time) S(name) S(info):<br>
     * [CALL] ボタンのついたウィンドウが表示される。これはBOTなどの不正者チェックに
     * 使われる机能らしい。名前をダブルクリックするとC_RequestWhoが飞び、クライアントの
     * フォルダにbot_list.txtが生成される。名前を选択して+キーを押すと新しいウィンドウが开く。
     */
    public static final int CALL_SOMETHING = 45;
    /**
     * C(id): 大圆形竞技场、混沌的大战.<br>
     * id - 1:开始 2:取消 3:结束
     */
    public static final int MSG_COLOSSEUM = 49;
    /** 血盟情报HTML. */
    public static final int HTML_CLAN2 = 51;
    /** 料理清单. */
    public static final int COOK_WINDOW = 52;
    /** 状态图示:料理 :C(type) H(time):. */
    public static final int ICON_COOKING = 53;
    /** 鱼上钩的图示. */
    public static final int FISHING = 55;
    /** 状态图示 :魔法娃娃. */
    public static final int ICON_MAGIC_DOLL = 56;
    /** 状态图示:智慧(慎重)药水. */
    public static final int ICON_WISDOM_POTION = 57;
    /** 状态图示:水之元气. */
    public static final int ICON_WATER_LIFE = 59;
    /** 状态图示:三段加速. */
    public static final int ICON_THIRD_SPEED = 60;
    /** 提示信息:目前游戏时间 %分钟, 剩下 %个商品. */
    public static final int MSG_GAMETIME_COMMODITY = 61;
    /** 同盟目录HTML. */
    public static final int HTML_ALLIANCE = 62;
    /** 状态图示:锁链剑 (弱点曝光 LV1~LV3)[C(time)2、3、4] // time >> 2. */
    public static final int ICON_WEAKNESS = 75;
    /** 提示信息:攻城战开始了 占领城的血盟如下. */
    public static final int MSG_WAR_START = 78;
    /** 提示信息:攻城战结束了 占领城的血盟如下. */
    public static final int MSG_WAR_OVER = 79;
    /** 提示信息:攻城战正在进行 占领城的血盟如下. */
    public static final int MSG_WAR_IN_PROGRESS = 80;
    /** 状态图示:殷海萨祝福 C(祝福指数:0-255). */
    public static final int ICON_YIN_HEJSA = 82;
    /** + 闪避率. */
    public static final int DODGE_RATE_PLUS = 88;
    /** 技能图示:龙之血痕. */
    public static final int ICON_BLOOD_STAIN = 100;
    /** - 闪避率. */
    public static final int DODGE_RATE_MINUS = 101;
    /** 龙门视窗. */
    public static final int DRAGON_GATE = 102;
    /** 3.3 组队系统(更新已有的队员信息). */
    public static final int UPDATE_OLD_PART_MEMBER = 104;
    /** 3.3 组队系统(更新新加入的队员信息). */
    public static final int PATRY_UPDATE_MEMBER = 105;
    /** 3.3 组队系统(委任新队长). */
    public static final int PATRY_SET_MASTER = 106;
    /** 3.3 组队系统(更新队伍信息,所有队员). */
    public static final int PATRY_MEMBERS = 110;
    /** 提示信息:向用户%s发送了%s地区的位置信息。. */
    public static final int MSG_ZONE = 111;
    /** 托管了道具HTML[角色名称、道具名称、时间:日时分秒]. */
    public static final int HTML_MANAGED_ITEM = 117;
    /** 提示信息:因神秘之气渗到体内，散发出潜力。. */
    public static final int MSG_MYSTERY_GAS = 118;
    /** 血盟情报 联合HTML. */
    public static final int HTML_CLAN_ALLIANCE = 119;
    /** 状态图示:盾型ICON (安全服务提升防御力。). */
    public static final int ICON_SECURITY_SERVICES = 125;
    /** 状态图示:蝙蝠型ICON (受波塞顿的支持!). */
    public static final int ICON_POSEIDON_SUPPORT = 127;

    /**
     * 封包盒子.
     * 
     * @param subCode
     *            - 子码
     */
    public S_PacketBox(final int subCode) {
        this.writeC(Opcodes.S_OPCODE_PACKETBOX);
        this.writeC(subCode);

        switch (subCode) {
            case MSG_WAR_INITIATIVE: // 已经掌握了城堡的主导权。 (音乐变化)
            case MSG_WAR_OCCUPY: // 已占领城堡
            case MSG_MARRIED: // 俩人的结婚在所有人的祝福下完成。 (音乐变化)
            case MSG_FEEL_GOOD: // \f1你觉得舒服多了
            case MSG_CANT_LOGOUT: // 战斗中无法重新开始
            case LOGOUT: // 角色选择视窗
            case FISHING: // 鱼上钩的图示
            case ICON_SECURITY_SERVICES: // 安全服务提升防御力。
            case ICON_POSEIDON_SUPPORT: // 受波塞顿的支持!
                break;
            case CALL_SOMETHING: // GM WHO
                this.callSomething();
            default:
                break;
        }
    }

    /**
     * 封包盒子.
     * 
     * @param subCode
     *            - 子码
     * @param value
     *            - 值
     */
    public S_PacketBox(final int subCode, final int value) {
        this.writeC(Opcodes.S_OPCODE_PACKETBOX);
        this.writeC(subCode);

        switch (subCode) {
            case ICON_BLUEPOTION: // 蓝水
            case ICON_CHATBAN: // 禁言
            case ICON_I2H: // 圣结界
            case ICON_POLYMORPH: // 变身
                this.writeH(value); // time
                break;
            case MSG_WAR_BEGIN: // %s的攻城战开始
            case MSG_WAR_END: // %s的攻城战结束
            case MSG_WAR_GOING: // %s的攻城战正在进行中
                this.writeC(value); // castle id
                this.writeH(0); // ?
                break;
            case MSG_SMS_SENT: // 您没有发送出任何简讯。/ 您共发出 %d 通天堂简讯。
            case WEIGHT: // 重量(30段阶)
            case FOOD: // 饱食度(30段阶)
                this.writeC(value);
                break;
            case MSG_ELF: // 忽然全身充满了%s的灵力。
            case MSG_RANK_CHANGED: // 你的阶级变更为%s
            case MSG_COLOSSEUM: // 大圆形竞技场，混沌的大战开始！结束！取消！
                this.writeC(value); // msg id
                this.writeC(0);
                break;
            case MSG_LEVEL_OVER: // 等级%d以下才能使用此道具
                this.writeC(0); // ?
                this.writeC(value); // 0-49以外不显示
                break;
            case COOK_WINDOW: // 料理清单
                this.writeC(0xdb); // ?
                this.writeC(0x31);
                this.writeC(0xdf);
                this.writeC(0x02);
                this.writeC(0x01);
                this.writeC(value); // level
                break;
            case DODGE_RATE_PLUS: // + 闪避率
                this.writeC(value);
                this.writeC(0x00);
                break;
            case DODGE_RATE_MINUS: // - 闪避率
                this.writeC(value);
                break;
            case ICONS2: // 状态图示
                this.writeC(0x00);
                this.writeC(0x00);
                this.writeC(0x00);
                this.writeC(value); // 闪避图示 (幻术:镜像、黑妖:闇影闪避)
                break;
            default:
                break;
        }
    }

    /**
     * 封包盒子.
     * 
     * @param subCode
     *            - 子码
     * @param type
     *            - 值
     * @param time
     *            - 时间(单位:秒)
     */
    public S_PacketBox(final int subCode, final int type, final int time) {
        this.writeC(Opcodes.S_OPCODE_PACKETBOX);
        this.writeC(subCode);

        switch (subCode) {
            case ICON_COOKING: // 料理
                if (type == 54) { // 象牙塔妙药
                    this.writeC(0x12);
                    this.writeC(0x0c);
                    this.writeC(0x0c);
                    this.writeC(0x07);
                    this.writeC(0x12);
                    this.writeC(0x08);
                    this.writeH(0x0000); // 饱和度 值:2000，饱和度100%
                    this.writeC(type); // 类型
                    this.writeC(0x2a);
                    this.writeH(time); // 时间
                    this.writeC(0x0); // 负重度 值:242，负重度100%
                } else if (type != 7) {
                    this.writeC(0x12);
                    this.writeC(0x0b);
                    this.writeC(0x0c);
                    this.writeC(0x0b);
                    this.writeC(0x0f);
                    this.writeC(0x08);
                    this.writeH(0x0000); // 饱和度 值:2000，饱和度100%
                    this.writeC(type); // 类型
                    this.writeC(0x24);
                    this.writeH(time); // 时间
                    this.writeC(0x00); // 负重度 值:242，负重度100%
                } else {
                    this.writeC(0x12);
                    this.writeC(0x0b);
                    this.writeC(0x0c);
                    this.writeC(0x0b);
                    this.writeC(0x0f);
                    this.writeC(0x08);
                    this.writeH(0x0000); // 饱和度 值:2000，饱和度100%
                    this.writeC(type); // 类型
                    this.writeC(0x26);
                    this.writeH(time); // 时间
                    this.writeC(0x00); // 负重度 值:240，负重度100%
                }
                break;
            case MSG_DUEL: // 结束决斗。 (音乐变化)
                this.writeD(type); // 对方ID
                this.writeD(time); // 自己ID
                break;
            case ICON_MAGIC_DOLL: // 魔法娃娃
                if (type == 32) { // 爱心图示
                    this.writeH(time);
                    this.writeC(type);
                    this.writeC(12);
                } else { // 魔法娃娃图示
                    this.writeH(time);
                    this.writeC(0);
                    this.writeC(0);
                }
                break;
            default:
                break;
        }
    }

    /**
     * 封包盒子.
     * 
     * @param subCode
     *            - 子码
     * @param id
     *            - 值
     * @param name
     *            - 对象名
     * @param clanName
     *            - 血盟名
     */
    public S_PacketBox(final int subCode, final int id, final String name,
            final String clanName) {
        this.writeC(Opcodes.S_OPCODE_PACKETBOX);
        this.writeC(subCode);

        switch (subCode) {
            case MSG_WIN_LASTAVARD: // %s 血盟的 %s打败了反王 %s 血盟成为新主人
                this.writeD(id); // 血盟ID或者什么？
                this.writeS(name);
                this.writeS(clanName);
                break;
            default:
                break;
        }
    }

    /**
     * 封包盒子.
     * 
     * @param subCode
     *            - 子码
     * @param names
     *            - 对象数组
     */
    public S_PacketBox(final int subCode, final Object[] names) {
        this.writeC(Opcodes.S_OPCODE_PACKETBOX);
        this.writeC(subCode);

        switch (subCode) {
            case ADD_EXCLUDE2: // XXX 开启拒绝名单
                this.writeC(names.length);
                for (final Object name : names) {
                    this.writeS(name.toString());
                }
                break;
            default:
                break;
        }
    }

    /**
     * 封包盒子.
     * 
     * @param subCode
     *            - 子码
     * @param name
     *            - 对象名
     */
    public S_PacketBox(final int subCode, final String name) {
        this.writeC(Opcodes.S_OPCODE_PACKETBOX);
        this.writeC(subCode);

        switch (subCode) {
            case ADD_EXCLUDE: // XXX 增加到拒绝名单
            case REM_EXCLUDE: // XXX 移除出拒绝名单
            case MSG_TOWN_LEADER: // 新村长由%s选出
                this.writeS(name);
                break;
            default:
                break;
        }
    }

    /**
     * 召唤.
     */
    private void callSomething() {
        final Iterator<L1PcInstance> itr = L1World.getInstance()
                .getAllPlayers().iterator();

        this.writeC(L1World.getInstance().getAllPlayers().size());

        while (itr.hasNext()) {
            final L1PcInstance pc = itr.next();
            final Account acc = Account.load(pc.getAccountName());

            // 时间情报 とりあえずログイン时间を入れてみる
            if (acc == null) {
                this.writeD(0);
            } else {
                final Calendar cal = Calendar.getInstance(TimeZone
                        .getTimeZone(Config.TIME_ZONE));
                final long lastactive = acc.getLastActive().getTime();
                cal.setTimeInMillis(lastactive);
                cal.set(Calendar.YEAR, 1970);
                final int time = (int) (cal.getTimeInMillis() / 1000);
                this.writeD(time); // JST 1970 1/1 09:00 が基准
            }

            // 角色信息
            this.writeS(pc.getName()); // 半角最多12字符
            this.writeS(pc.getClanname()); // 出现在[]内的文字信息。半角最多12字符
        }
    }

    @Override
    public byte[] getContent() {
        if (this._byte == null) {
            this._byte = this.getBytes();
        }

        return this._byte;
    }

    @Override
    public String getType() {
        return S_PACKETBOX;
    }
}
